// Authors: Matthew DeNovio

#include "Game.h"

#include <iostream>

using namespace std;



// Constructor
Game::Game(void)
{
	_currentGameState = openworld;
	_currentLocation = mainworld;
	_gameCamera.init();
	_gameWorld.init(&_gameCamera);
	createWorld();
	_bShiftCamera = false;
}


Game::~Game(void)
{
}

// Initializes the Game
void Game::startUpGame()
{
	_gameWorld.loadMap(_currentLocation);

	// Moves Character Position to location and Draw it
	moveCharacter();
	drawCharacter();

	currentTime = timeGetTime();

	amtMoved = _gameCamera.TILE_DIM;

	playGame();
}

// create the world for the current map
void Game::createWorld()
{
	switch(_currentLocation)
	{
	case mainworld:		//gameWorld.loadMap(currentLocation);	
		break;


	}

}

// Display world
void Game::displayBoard()
{

}

// Moves the Character and Draws it on the Board
void Game::moveCharacter()
{
	// Move
	_player.Location().x = (_gameCamera.getBottomRight().x - _gameCamera.getTopLeft().x - _gameCamera.TILE_DIM) / 2 + _gameCamera.getTopLeft().x ;
	_player.Location().y = (_gameCamera.getBottomRight().y - _gameCamera.getTopLeft().y - _gameCamera.TILE_DIM) / 2 + _gameCamera.getTopLeft().y;
}

void Game::drawCharacter()
{
	// Draws Character according to position
	// Also Draws Character every other scroll so it doesnt slow down as much

	//if(!(_player.Location().x % 2) && !(_player.Location().y % 2))
	//{
	if(_shiftAmount.x)
	{
		if(_shiftAmount.x > 0)
			_player.DrawRightImage(&_gameCamera);
		else
			_player.DrawLeftImage(&_gameCamera);
	}
	else if (_shiftAmount.y)
	{
		if(_shiftAmount.y > 0)
			_player.DrawDownImage(&_gameCamera);
		else
			_player.DrawUpImage(&_gameCamera);
	}
	else
	{
		_player.DrawDownImage(&_gameCamera);
	}
}


// Game Loop, Updates the Game and Draws changes on Screen
#pragma region GameLoop
void Game::playGame()
{
	while(true)
	{
		updateTime();
		getInput();
		updateGame();
		drawGame();
	}
}
#pragma endregion

// Update Time 
#pragma region UpdateTime

void Game::updateTime()
{
	pastTime = currentTime;
	currentTime = timeGetTime();
	dt = currentTime - pastTime;

}

#pragma endregion

// User Input
#pragma region UserInput

// Get the user Input
#pragma region GetInput

void Game::getInput()
{

	waitTime += dt;

	if(waitTime > INPUT_WAIT && !_bShiftCamera && scrollWaitTime > SCROLL_WAIT)
	{
		//cin.clear();

		_shiftAmount.x = 0;
		_shiftAmount.y = 0;
		_bShiftCamera = false;


		// Enter Key
		if(checkKeyBoardState(13))
		{
			waitTime = 0;
		}

		// Up
		else if(checkKeyBoardState(38) || checkKeyBoardState('w') || checkKeyBoardState('W'))
		{
			_shiftAmount.y = -1;
			_bShiftCamera = true;
			waitTime = 0;
		}

		// Right
		else if(checkKeyBoardState(39) || checkKeyBoardState('d') || checkKeyBoardState('D'))
		{
			_shiftAmount.x = 1;
			_bShiftCamera = true;
			waitTime = 0;
		}

		// Down
		else if(checkKeyBoardState(40) || checkKeyBoardState('s') || checkKeyBoardState('S'))
		{
			_shiftAmount.y = 1;
			_bShiftCamera = true;
			waitTime = 0;
		}

		// Left
		else if(checkKeyBoardState(37) || checkKeyBoardState('a') || checkKeyBoardState('A'))
		{
			_shiftAmount.x = -1;
			_bShiftCamera = true;
			waitTime = 0;
		}

	}

}

#pragma endregion

// Check and See if key is pressed
#pragma region CheckKeyState

bool Game::checkKeyBoardState(U8 key)
{
	return GetKeyState(key) & 0x800;		// if high order is 1, then its down
}

#pragma endregion

#pragma endregion

// Updates the Game depending on current game state
#pragma region UpdateGame

void Game::updateGame()
{
	switch(_currentGameState)
	{
#pragma region OpenWorld

	case openworld: 



		scrollWaitTime += dt;

		
			// If Should shift, shift it
			if(_bShiftCamera && scrollWaitTime > SCROLL_WAIT)
			{
				// Check Boundrys of Level
				if(checkCameraBoundrys())
				{
					// Check Boundrys of next Tile

					if(waitTime || tileWalkable())
					{
						_bShiftCamera = _gameCamera.shiftCamera(_shiftAmount.x,_shiftAmount.y);
						scrollWaitTime = 0;
						_bVisualChanges = true;
						moveCharacter();
					}
					else
					{
						_bShiftCamera = false;
						waitTime = INPUT_WAIT;
					}
				}
				else
				{
						_bShiftCamera = false;
						waitTime = INPUT_WAIT;
				}
			}

		


		break;

#pragma endregion

#pragma region Battle 

	case battle:
		break;

#pragma endregion

#pragma region Paused

	case paused:
		break;

#pragma endregion

#pragma region Dialogue

	case dialogue:
		break;

#pragma endregion

#pragma region Default

	default :
		cout << "Stop Cheating";
		break;

#pragma endregion

	}

}

#pragma endregion

// Draw Screen
#pragma region DrawScreen

void Game::drawGame()
{
	if (_bVisualChanges)			// Draw when there are visual changes
	{		
		// Draw when the Scroll Wait resets
		if(!scrollWaitTime)
		{
			_gameWorld.drawOffsetParts(_shiftAmount , _player.Location());
			drawCharacter();
			_gameCamera.removeAnnoyingLines(_shiftAmount);

		}
		_bVisualChanges = false;
	}

}

#pragma endregion


// Returns if the next move is out side the bounds
bool Game::checkCameraBoundrys()
{
	if(_shiftAmount.x)
	{
		// Left
		if(_shiftAmount.x < 0)
			return (_gameCamera.getTopLeft().x != 0);
		// Right
		else
			return _gameCamera.getBottomRight().x != _gameWorld.Width() * _gameCamera.TILE_DIM;
	}
	else if (_shiftAmount.y)
	{
		// Up
		if(_shiftAmount.y < 0)
			return (_gameCamera.getTopLeft().y != 0);
		// Down
		else
			return _gameCamera.getBottomRight().y != _gameWorld.Height() * _gameCamera.TILE_DIM;
	}
	return 1;
}

bool Game::tileWalkable()
{
	return (_gameWorld.GetTile(_player.Location().x / _gameCamera.TILE_DIM + _shiftAmount.x, _player.Location().y / _gameCamera.TILE_DIM + _shiftAmount.y)->isWalkable());

}


